﻿using RabbitMQ.Client;
using RabbitMQ.Client.Events;
using System;
using System.Collections.Generic;
using System.Text;

namespace Maltose.MessageQueue.Subscibe
{
    /// <summary>
    /// 订阅交换通道信息
    /// </summary>
    public class MessageQueueExchangeSubscibe : MessageQueueHost
    {
        /// <summary>
        /// 事件参数
        /// </summary>
        /// <param name="message">接受参数内容</param>
        /// <param name="deliveryTag">用于确定消费者的tag</param>
        public delegate void ReceivedEventHandler(string message, ulong deliveryTag);

        /// <summary>
        /// 接受事件
        /// </summary>
        public event ReceivedEventHandler OnReceived;

        /// <summary>
        /// 是否自动确定消息 默认false 需要手动确定
        /// </summary>
        public bool AutoAck { get; set; } = false;

        /// <summary>
        /// 消息队列数量 默认=1 确保忙碌不在分发
        /// </summary>
        public ushort PrefetchCount { get; set; } = 1;

        /// <summary>
        /// 交换信息类型
        /// </summary>
        public ExchangeSubscibeType EType = ExchangeSubscibeType.Fanout;

        /// <summary>
        /// 路由
        /// </summary>
        public string RoutingKey { get; set; } = "";

        /// <summary>
        /// 是否是永久的 默认true
        /// </summary>
        public bool Durable { get; set; } = true;

        /// <summary>
        /// 是否自动删除 默认 false
        /// </summary>
        public bool AutoDelete { get; set; } = false;

        /// <summary>
        /// 额外参数 默认 null
        /// </summary>
        public Dictionary<string, object> Arguments { get; set; } = null;

        /// <summary>
        /// 订阅的交换信息
        /// </summary>
        public string Exchange { get; }

        /// <summary>
        /// 订阅主题消息
        /// </summary>
        /// <param name="connect"></param>
        /// <param name="exchange"></param>
        public MessageQueueExchangeSubscibe(MessageQueueConnect connect, string exchange) : base(connect)
        {
            Exchange = exchange;
        }



        /// <summary>
        /// 开始订阅
        /// </summary>
        public void Subscibe()
        {
            Channel.ExchangeDeclare(Exchange, EType.ToEnumDescription(), Durable, AutoDelete, Arguments);

            var queueName = Channel.QueueDeclare().QueueName;
            Channel.QueueBind(queue: queueName, exchange: Exchange, routingKey: RoutingKey);

            //公平分发
            Channel.BasicQos(prefetchSize: 0, prefetchCount: PrefetchCount, global: false);

            var eventingBasic = new EventingBasicConsumer(Channel);
            eventingBasic.Received += EventingBasic_Received;
            Channel.BasicConsume(queue: queueName, autoAck: AutoAck, consumer: eventingBasic);
        }

        /// <summary>
        /// 接受事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void EventingBasic_Received(object sender, BasicDeliverEventArgs e)
        {
            var message = Encoding.UTF8.GetString(e.Body.ToArray());
            OnReceived?.Invoke(message, e.DeliveryTag);
        }


        /// <summary>
        /// 手动确定消息
        /// </summary>
        /// <param name="deliveryTag"></param>
        /// <param name="multiple"></param>
        public void BasicAck(ulong deliveryTag, bool multiple = false)
        {
            Channel.BasicAck(deliveryTag, multiple);
        }
    }
}
